I want to send a docx file to the client in the response of a get request:
Here's the Laravel controller code:
public function file($id)
{
$dlink = resource_path('temp/' . $id . '.docx');
$headers = [
'Content-Type' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
];
return response()->download($dlink, $id . '.docx', $headers);
}
VueJS code:
axios.get(`${location.protocol}//${location.host}/api/download/${response.data}`,
{ responseType: "arraybuffer" }
)
.then(response => {
this.downloadFile(response);
})
.catch(err => alert(err));
downloadFile(response) {
var newBlob = new Blob([response.body], {
type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
});
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(newBlob);
return;
}
const data = window.URL.createObjectURL(newBlob);
var link = document.createElement("a");
link.href = data;
link.download = "resume.docx";
link.click();
setTimeout(function() {
window.URL.revokeObjectURL(data);
}, 100);
}
It doesn't show any error. but downloads a corrupted 9bytes docx file.
changing response.body to response.data did the job.
Related
I'm trying to send some files from my server but after zipping, sending and downloading the files on the client side the files inside the zip are corrupted.
I've tried to save and open the files directly from the backend to verify that the files are ok and it worked.
my php code:
public function download(Procedure $procedureId, UserInfo $userId,Request $request)
{
$userFiles = $userId->files()->where("procedure_id",$procedureId->id)->get()->toArray();
$collectFiles = collect($userFiles);
$files = $collectFiles->map(function($file){
return ['path'=>$file['path'],'fileName'=>$file['real_name']];
});
// $procedureUserInfo = ProcedureUserInfo::find($request->procedureUserInfoId)->attributesToArray();
// $signedPdf = $procedureUserInfo->pdfPath;
$zip = new ZipArchive;
$zipFile ='app/public/compressedZips/'."{$procedureId->name}_{$userId->firstName}.zip";
if( $zip->open(storage_path($zipFile),ZipArchive::CREATE)===TRUE){
foreach($files as $file){
$filePath = Storage::disk("public")->path($file['path']);
$zip->addFile($filePath,$file["fileName"]);
}
$zip->close();
}
return response()->download(storage_path($zipFile),
"{$procedureId->name}_{$userId->firstName}".Carbon::now().".zip"
,["Content-Type"=>'application/zip','Content-Transfer-Encoding'=>"binary"]);
}
my client code (reactjs):
const downloadFile = async ({procedureUserInfoId, procedureTypetype, userId,procedureId,})=> {
try {
let url = "";
store.dispatch(startLoading("downloading..."));
const { data } = await Axios.get(
`procedures/files/${procedureId}/${userId}/download`,
{
params: { procedureUserInfoId, procedureId },
headers: { Authorization: `Bearer ${store.getState().auth?.token}` },
responseType: "arraybuffer",
}
);
if (data) {
let bytes = new Uint8Array(data);
const blob = new Blob([data], { type: "application/zip" });
const url = window.URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.click();
}
} catch (error) {
console.log(error);
// store.dispatch(setError());
} finally {
store.dispatch(stopLoading());
}
};
I have a hyperlink button on click of this, i want to fetch image from database and get it downloaded on user side with use of laravel and vue js. Below is my code for script file
getImage: function() {
axios.get('/getImage/' + this.form.cashout_id )
.then(function (r)
{
const url = window.URL.createObjectURL(new Blob([r.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', 'file.'+r.headers.ext); //or any other extension
document.body.appendChild(link);
link.click();
//hide loader
i.loader = false
})
.catch(function (error) {
alert('Error');
});
},
and now this is my controller code where image is being fetched.
public function getimage($id)
{
$cashout = CashOutDetail::findorfail($id);
$storage_date = Carbon::parse($cashout['recorded_date']);
return response()->download(
storage_path('app/cashoutdetails/'. $storage_date->year .'/' . $storage_date->format('M') . '/'. $cashout->bank_receipt),
'filename.jpg',
['Content-Type' => 'image/jpg']
);
}
Issue is that my image is being fetched and displayed in console window but unable to download. Can anybody help?
You should try:
axios({
method: 'GET',
url: '/getImage/123.jpg',
responseType: 'blob', // <-<<<<<<<<<<
}).then((response) => {
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', '123.jpg');
document.body.appendChild(link);
link.click();
});
I'm trying to save image to php application (made with laravel 6.0) using React Native. Here is my react native image picker
var ImagePicker = NativeModules.ImageCropPicker;
here is my image save function
addImages = async () => {
const { image, images } = this.state
const access_token = await AsyncStorage.getItem('access_token')
try {
let data = new FormData();
images.map((image, i) => {
data.append('id', id);
data.append('uri', image.uri);
data.append('type', image.mime);
data.append('name', 'test.jpg');
});
fetch(apiConfig.apiUrl + '/api/save-image', {
method: 'POST',
headers: {
'Content-Type' : 'multipart/form-data',
'Authorization': 'Bearer ' + access_token,
},
body:data
})
.then(function (response) {
return response.json();
})
.then(function (data) {
try {
console.log(data);
} catch (error) {
console.log(error);
}
}.bind(this))
.catch((error) => {
console.log(error)
});
}catch (error) {
console.log(error)
}
}
Here is my php code
public function saveImage(Request $request)
{
header( "Access-Control-Allow-Methods' => 'POST, GET, OPTIONS, PUT, DELETE");
header("Access-Control-Allow-Origin: *");
try {
$file= array('file'=>$request->uri);
Storage::disk('public')->put($request->imgName,File::get($file->file));
return response()->json(['true'=>'Successfully Created'], 200);
} catch (\Exception $e) {
Log::info('vehicle image: ', [$e->getMessage()]);
return response()->json(['error'=>$e], 200);
}
}
When I try to save I'm getting SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data.
when I return the $request->uri I'm getting something like this file:///data/user/0/com.carup/cache/react-native-image-crop-picker/IMG_20191103_161929.jpg
How can I fix this?
How can I fix this?
You need to specify file name as the third parameter to data.append:
data.append('file', image.uri, 'test.jpg');
Finally I have fixed it with Base64 method. Here is my code.
pick images with base64
pickMultipleBase64=()=> {
ImagePicker.openPicker({
multiple: true,
width: 300,
height: 300,
includeBase64: true,
includeExif: true,
}).then(images => {
this.setState({
images: images.map(image => {
return {uri: `data:${image.mime};base64,`+ image.data, width: image.width, height: image.height,type:image.mime}
}),
});
}).catch(e => alert(e));
}
And uploaded with other details like this
addImages = async () => {
const { image, images, stockNo } = this.state
const access_token = await AsyncStorage.getItem('access_token')
if(access_token == null) {
return(
this.gotoLogin()
)
}
this.setState({
isLoading:true,
message:'',
status:true
})
try {
let data = new FormData();
images.map((image, i) => {
data.append('id', id);
data.append('stock', stockNo);
data.append('chassis', chassis_no);
data.append('file'+i, this.state.images[i].uri);
data.append('type'+i, this.state.images[i].type);
imageCount++
});
data.append('imageCount', imageCount);
// console.log(data);
fetch(apiConfig.apiUrl + '/api/save-image', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + access_token,
},
body:data
})
.then(function (response) {
return response.json();
})
.then(function (data) {
console.log(data);
imageCount = 0
try {
this.setState({
isLoading: false,
message:data.true ? data.true:data.error,
messageColor:data.true ? CarColors.success : CarColors.error,
btnStatus:true
// chassis:''
})
if(data.true){
this.setState({
image:null,
images: null,
})
}
} catch (error) {
this.removeToken();
console.log('1 '+error);
}
}.bind(this))
.catch((error) => {
this.setState({
isLoading: false,
message:'error',
messageColor:CarColors.error,
})
console.log(error)
});
}catch (error) {
console.log(error)
}
And my php(laravel) code is like this. Here I have created a new folder (with vehicle id) in storage and save images to separate folders.
public static function saveImage($request)
{
$dir = "./storage/vehicle/" . $request->id;
if (is_dir($dir) === false) {
mkdir($dir);
}
DB::beginTransaction();
try {
for ($i = 0; $i < $request->imageCount; $i++) {
$type = [];
$file = 'file' . $i;
$mime = 'type' . $i;
$data = $request->$file;
$type = explode('/', $request->$mime);
$extension = $type[1];
list($type, $data) = explode(';', $data);
list(, $data) = explode(',', $data);
$data = base64_decode($data);
$Imgdata =Images::create([
'vehicle_id' => $request->id,
'img_name' => $i.'.'.$extension,
'img_ext' => $extension,
'img_order' => '0',
]);
Storage::disk('vehicle')->put($request->id . '/' . $i . '.' . $extension, $data);
}
//Update Vehicle table ImageStatus
$Vehicle = Vehicle::where('id',$request->id)->update([
'img_status' => '1',
]);
return response()->json(['true' => 'Successfully Uploaded'], 200);
} catch (\Exception $e) {
DB::rollback();
Log::info('vehicle image name save issue: ', [$e->getMessage()]);
return 'false';
}
}
Hope this will help others who are going to upload multiple images with react native
Like the title says, I'm trying to do an image upload from VueJs to a Laravel endpoint. I discovered that the only way(if there is another please tell me) is to send the base64 of the image through the request. On the Vue side I think everything is covered.
However, on the Laravel side is where it gets complicated. I can't decode the base64 string that gets passed, and when I try to store the image in my AWS S3 bucket, it doesn't store properly. Here is the code:
VueJS
<template>
<input type="file" name="image" class="form-control" #change="imagePreview($event)">
</template>
methods: {
submitForm(){
axios.defaults.headers.post['Content-Type'] = 'multipart/form-data';
axios.post(this.$apiUrl + '/article', {
image: this.image
}).then(response => {
flash(response.data.message, 'success');
}).catch(e => {
console.log(e);
})
},
imagePreview(event) {
let input = event.target;
if (input.files && input.files[0]) {
var reader = new FileReader();
let vm = this;
reader.onload = e => {
this.previewImageUrl = e.target.result;
vm.image = e.target.result;
}
reader.readAsDataURL(input.files[0]);
}
}
}
Laravel:
$this->validate($request, [
'image' => 'required',
]);
// return response()->json(base64_decode($request->image));
$timestampName = microtime(true) . '.jpg';
$url = env('AWS_URL') . '/article_images/' .$timestampName;
Storage::disk('s3')->put($timestampName, base64_decode($request->image));
If I add the image validation rule, it says it's not an image..
I would also like to retrieve the extension if possible.
you can do it using FormData in JS part and use getClientOriginalExtension() on the file to get the extension in Laravel.
VueJS
imagePreview(event) {
let selectedFile = event.target.files[0];
vm.image = selectedFile;
}
submitForm(){
let fomrData = new FormData();
formData.append('image', vm.image);
axios.post(this.$apiUrl + '/article', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
.then(response => {
flash(response.data.message, 'success');
})
.catch(e => {
console.log(e);
});
}
Laravel
$this->validate($request, [
'image' => 'required',
]);
$image = $request->file('image');
$extension = $image->getClientOriginalExtension(); // Get the extension
$timestampName = microtime(true) . '.' . $extension;
$url = env('AWS_URL') . '/article_images/' .$timestampName;
Storage::disk('s3')->put($url, file_get_contents($image));
Here is a link that might be useful
Hope that it helps.
I'm using laravel 4.2 and currently I don't how to save a csv file into public\csv\ directory using AJAX. I'm still finding some answers. Maybe someone can help me with this.
Here's my code:
In blade view:
{{Form::open(['route' => 'file_upload', 'files' => true, 'id' => 'upload_form', 'method' => 'POST'])}}
{{Form::file('csv_upload', ['id' => 'uploaded_file', 'accept' => 'text/csv'])}}
{{Form::submit('submit', ['class' => 'btn btn-primary btn-xs', 'id' => 'upload'])}}
{{Form::close()}}
Javascript Ajax:
var ajax_ready = 1
var token = {{Session::get('_token')}}
if($.type(originalOptions.data) === 'string') {
options.data = originalOptions.data+"&_token="+token;
}else if($.type(originalOptions.data) === 'object') {
//Here I got a new error
}else{
options.data = $.param(($.extend(originalOptions.data, {'_token':mmad_token})));
}
options.url = originalOptions.url.slice(0,originalOptions.url.indexOf("?_token="));
if (ajax_ready!=1){
jqXHR.abort();
}
ajax_ready = 0;
});
$('form#upload_form').on('submit', function(e){
e.preventDefault();
var uploadFile = $('#uploaded_file');
var ext = $("input#uploaded_file").val().split(".").pop().toLowerCase();
var file = $('input[name="csv_upload"]').val();
if($.inArray(ext, ["csv"]) === -1) {
alert("Please upload a .csv file!");
return false;
}
var csv = uploadFile[0].files;
var form = new FormData(this);
var csvFile = {lastModifed: csv[0].lastModified, fileName: csv[0].name, size: csv[0].size, fileType: csv[0].type};
$.post('{{ URL::route("file_upload") }}?_token={{Session::token()}}',{
data: form
}).done(function(response){
});
});
PHP:
public function upload_csv()
{
$inputs = Input::all();
$csvFile = $inputs['data']['fileName'];
$path = public_path().DIRECTORY_SEPARATOR.'csv'.DIRECTORY_SEPARATOR;
$path2 = public_path('csv/');
if(is_dir($path2))
{
#move_uploaded_file($csvFile, $path2.$csvFile); //This line can't move the uploaded files in my desired directory
}
return json_encode(['success' => 1, 'description' => 'Successfully Upload File']);
}
This code below does work when not using AJAX:
if(Input::hasFile('csv_upload'))
{
$file = Input::file('csv_upload');
$originalFilename = $file->getClientOriginalName();
$rules = ['csv_upload' => 'required|file:csv'];
$validate = Validator::make(['csv_upload' => $file], $rules);
if($validate->fails())
{
return json_encode(['error' => 1, 'description' => 'File must be in .csv format']);
}
$path = public_path('/csv/');
if(!file_exists($path))
{
mkdir($path);
}
}
Console.log of csv
You can not move file because when you submit form with ajax file is not being sent with ajax,For sending file you have to send file with FormData() javascript Object.
If you check in upload_csv controller by putting print_r($_FILES); you will get empty array.
So use FormData on client side for appending file, then try agian.
You aren't getting error beacuse you have used php Error Control Operators likes#move_uploaded_file($csvFile, $path2.$csvFile);.
if you need working example then tell me i will give it to you.
Code For Your Help:
1. In blade view:
<script type="text/javascript">
$('form#upload_form').on('submit', function(e){
e.preventDefault();
var uploadFile = $('#uploaded_file');
var ext = $("input#uploaded_file").val().split(".").pop().toLowerCase();
var file = $('input[name="mmad_csv_upload"]').val();
if($.inArray(ext, ["csv"]) === -1) {
alert("Please upload a .csv file!");
return false;
}
var csv = uploadFile[0].files;
var formData = new FormData($(this)[0]);
formData.append('uploaded_file', $("#uploaded_file")[0].files[0]);
formData.append('lastModifed', csv[0].lastModified);
formData.append('fileName', csv[0].name);
console.log(formData);
$.ajax({
url: '{{ URL::route("file_upload") }}',
type: 'POST',
data: formData,
async: true,
cache: false,
contentType: false,
processData: false,
success: function (returndata) { //alert(returndata); return false;
}
});
});
</script>
2.Controller
public function file_upload(Request $request)
{
$inputs = Input::all();
$csvFile = $inputs['fileName'];
$path = public_path().DIRECTORY_SEPARATOR.'csv'.DIRECTORY_SEPARATOR;
$path2 = public_path('/csv/');
if(is_dir($path2))
{
$success = $request->file('uploaded_file')->move($path2, $csvFile);
}
return json_encode(['success' => 1, 'description' => 'Successfully Upload File']);
}
To move the uploaded file to a new location, you should use the move method. This method will move the file from its temporary upload location (as determined by your PHP configuration) to a more permanent destination of your choosing:
Input::file('fileName')->move($destinationPath, $fileName);
If you need additional validations, you can check it at http://laravel.com/docs/5.1/requests#files
Default AJAX POST does not support file uploads. Use jQuery Form to upload files successfully. Full documentation of file upload at http://malsup.com/jquery/form/#file-upload
Below my example of a recentlty build script... My Controller uploads the files to S3, but is easy to be implemented with local storage.
var progress = function(event, position, total, percent) {
$(".progress-bar").width(percent + '%');
$(".progress-bar").html(percent + '%');
if(percent > 50) {
$(".progress-bar").css('color','#fff');
}
if(percent == 100) {
setTimeout(function(){
$(".progress").html('<span class="processing-msg">Processing... Please be patient!</span>');
$(".processing-msg").fadeIn('slow');
}, 1000);
}
}
var success = function(data) {
var obj = $.parseJSON(data);
$("#"+obj.hidden, parent.document).val(obj.filename);
var src = 'https://s3.amazonaws.com/spincms'+obj.path+'thumb_'+obj.filename;
$("#uploaded-"+obj.hidden, parent.document).html('<img class="img-circle uploaded-img" src="' + src + '">');
$(".progress").html('<span class="processing-msg-next">File has been uploaded and processed. Do not forget to submit the form!</span>');
}
var options = {
target: '#output',
uploadProgress: progress,
success: success,
resetForm: true
};
$(document).on('click', "#upload-now", function(e) {
$(".progress").html('<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100"></div>');
if($("#upload-form input[type=file]")[0].files.length == 0) {
$(".progress").html('<span class="processing-msg-next">No file selected!</span>');
return false;
} else {
var name = $("#upload-form input[name='name']").val();
var token = $("#upload-form input[name='_token']").val();
var file_name = $("#upload-form input[type=file]")[0].files[0].name;
$("#upload-form").ajaxSubmit(options);
}
}
});
Since you are using jQuery you can use the form plugin as it will make things much more easier for you to work with for example , this is the jquery part that you will use :
$(document).ready(function() {
// bind 'myForm' and provide a simple callback function
$('#upload_form').ajaxForm(function() {
alert("Your file has been uploaded, thanks");
});
});
and in your controller you can code it like :
pubilc function postUpload()
{
$success = false;
if(Request::ajax())
{
if(Input::hasFile('csv_upload'))
{
$file = Input::file('csv_upload');
if(!File::isDirectory(storage_path('csv'))) {
File::createDirectory(storage_path('csv'));
}
$file->move(storage_path('csv'), $file->getClientOriginalName());
// now your file is on app/storage/csv folder
$filePath = storage_path('csv/'.$file->getClientOriginalName());
$success = true;
}
}
return Response::json(['success'=>$success]);
}