I have a block of code which would upload the file into the Google Drive. My main issue here is that when the user clicks on the upload button, the MD5 hash of the file will be checked and compared with the MD5 hashes of other files in the Google Drive and if there is a duplicate, then a message pop-up should be displayed stating that the file is a duplicated file and the user would need to reupload the file again.
This is from my GetGoogleDrive.cshtml file.
#using (Html.BeginForm("UploadFile", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<p>
<label for="file">Upload file:</label>
<input type="file" name="file" id="file" />
<input type="submit" value="Upload" id="fileUpload" />
<script>
$('#fileUpload').click(function (e) {
if ($('#file').val() === "") {
Swal.fire({
title: 'Nothing',
text: 'No file selected',
type: 'error',
confirmButtonText: 'Again!!',
timer: 4000
})
}
else {
Swal.fire({
title: 'Wait awhile...',
text: 'File will be uploaded shortly',
type: 'success',
confirmButtonText: 'Okay, cool',
timer: 4000
})
}
});
</script>
The following code is for my upload file controller class.
[HttpPost]
public ActionResult UploadFile(HttpPostedFileBase file)
{
GoogleDriveFilesRepository.FileUpload(file);
return RedirectToAction("GetGoogleDriveFiles");
}
This is the code for my Google Drive Files model class.
public static void FileUpload(HttpPostedFileBase file)
{
if (file != null && file.ContentLength > 0)
{
DriveService service = GetService();
string path = Path.Combine(HttpContext.Current.Server.MapPath("~/GoogleDriveFiles"),
Path.GetFileName(file.FileName));
file.SaveAs(path);
HashGenerator(path);
compareHash(HashGenerator(path));
var FileMetaData = new Google.Apis.Drive.v3.Data.File();
FileMetaData.Name = Path.GetFileName(file.FileName);
FileMetaData.MimeType = MimeMapping.GetMimeMapping(path);
FilesResource.CreateMediaUpload request;
using (var stream = new System.IO.FileStream(path, System.IO.FileMode.Open))
{
request = service.Files.Create(FileMetaData, stream, FileMetaData.MimeType);
request.Fields = "id";
request.Upload();
}
}
}
Where should I generate the MD5 hash value of the file? In the C# or the JS?
Related
I am using ElementUi uploader and i need to send my file with the rest of my form data, but it doesn't seem to send right details of photo to back-end:
Screenshots
Console log when i select an image
Data that sent to back-end
Code
photo input
<el-upload
action="#"
:limit="1"
:multiple="false"
:on-change="photoChanged"
:on-exceed="handleExceed"
list-type="picture-card"
:on-remove="handleRemove"
:on-preview="handlePictureCardPreview"
:before-remove="beforeRemove"
:auto-upload="false">
<i slot="default" class="el-icon-plus"></i>
</el-upload>
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
Script
export default {
data() {
return {
dialogImageUrl: '',
dialogVisible: false,
form: {
name: '',
slug: '',
price: '',
new_price: '',
sku: '',
qty: 1,
active: '',
photo: '',
shortDesc: '',
longDesc: '',
region: '',
date1: '',
date2: '',
type: [],
tags: [],
brand_id: '',
categories: [],
resource: '',
user_id: ''
}
}
},
methods: {
onSubmit(e) { //send data to back-end
e.preventDefault();
axios.post('/api/admin/products/store', this.form)
.then(res => {
console.log(res);
})
.catch(error => {
console.log(error);
})
},
handleRemove(file) {
this.form.photo = ''; // remove photo from from when it's removed
},
photoChanged(file, fileList){
this.form.photo = file.raw; // add photo to form when it's selected
console.log('file', file) // screenshot 1
console.log('raw', file.raw) //screenshot 2
},
handlePictureCardPreview(file) {
this.dialogImageUrl = file.url;
this.dialogVisible = true;
},
handleExceed(files, fileList) {
this.$message.warning(`The limit is 1, you selected ${files.length} files this time, add up to ${files.length + fileList.length} totally, remove old image and try again.`);
},
beforeRemove(file) {
return this.$confirm(`Cancel the transfert of ${ file.name } ?`);
}
},
}
</script>
Any idea?
I have used FormData to send the photo or document to the server.
JavaScript FormData
<form id="myForm" name="myForm">
<div>
<label for="username">Enter name:</label>
<input type="text" id="username" name="username" v-model="imageData.name">
</div>
<div>
<label for="useracc">Enter account number:</label>
<input type="text" id="useracc" name="useracc" v-model="imageData.account">
</div>
<label for="userfile">Upload file:</label>
<input type="file" id="userfile" name="userfile">
</div>
<input type="submit" value="Submit!">
</form>
export default {
data() {
return {
imageData: {}
}
},
methods: {
uploadImageToServer() {
// 1.Save the form Data and return the new id to save the image
axios.post('/api/admin/products/store', this.imageData)
.then(res => {
if(res.id) {
//2. Save the image to id
let formData = new FormData();
let file = document.getElementById('userfile');
formData.append('file', file)
axios.post('/api/admin/products/image/{id}', formData)
.then(res => {
console.log(res)
})
}
})
.catch(err => {
console.log(err)
})
}
}
}
Here,
Both form data & file data maynot be send in single requst.
1. Saving the form data and return the id.
2. Saving the image data to the id.
Replace the html with 'element-ui' syntax. Ensure that your rest api receives the form data as the input.
convert your file to base64
when you select an image, use code below
onImageChange() {
let file = this.form.photo
if (file == '')
return;
this.createImage(file);
}
createImage(file) {
let reader = new FileReader();
let el = this
reader.onload = (e) => {
el.form.photo = e.target.files[0];
};
reader.readAsDataURL(file);
},
attach onImageChange function in your input file
Solved
Well I have decided to give up on sending image with rest of data to backend and upload image first with action="#" in my input and in return i get file name in my form and just send the file name with rest of form instead of sending image file.
<el-upload
action="/api/upload"
:on-success="handleAvatarSuccess"
.....>
methods: {
handleAvatarSuccess(res, file) {
this.form.photo = res.data;
},
}
So it sends my file to back-end as soon as it's selected and set the name of stored file in my form.photo and that name will be send with rest of my form inputs.
Hope it could be useful to others as well.
i want to fetch the file based on my applications_id and i want to see it in the bootstrap file input and i want to delete it and replace with a new file. how can i do it. below is what i have tried .can anyone help me .i am stuck.
this is my contoller function SoleProprietorController.php
public function uploadImages(Request $request, $applications_id)
{
$applications = new Applications;
// $KRAPIN = Input::get('KRA_unique_field');
$applications_id = Input::get('applications_id_unique_field');
if ($request->hasFile('breg_cert')) {
if ($request->file('breg_cert')->isValid()) {
// request()->breg_cert->move(public_path('breg_cert'), $imgName);
// $imgName = basename($request->breg_cert->store(public_path('breg_cert')));
$imgName = basename($request->breg_cert->move(public_path('breg_cert')));
$applications->breg_cert = $imgName;
}
return response()->json(['uploaded' => '/breg_cert/'.$imgName]);
}
}
this my web.php
Route::post('/uploadImages/{applications_id}', 'SoleProprietorController#uploadImages')->name('home');
this is my bootstrap file in my blade
<div class="col-md-4 mb-3">
<label for="validationServer023">Upload Business Registration Document</label>
<div class="form-group">
<div content="{{ csrf_token() }}" class="input-group input-file" name="Fichier1">
<input id="file-0a" name="breg_cert" value="" class="file" accept="text" type="file"> <br />
</div>
</div>
</div>
<script>
$("#file-0a").fileinput({
initialPreview: [
"<img src='/images/php' class='file-preview-image'>",
],
showUpload: true,
showRemove: true,
showCaption: true,
showPreview: true,
showClose: false,
autoOrientImage: true,
showUploadedThumbs: false,
uploadAsync: false,
uploadUrlThumb: false,
deleteUrl: "/public/KFS_Business_Registration_Certificates",
uploadUrl: "/uploadImages/{applications_id}",
// dataUrl: "/breg_cert/",
// uploadUrl: '/public/KFS_Business_Registration_Certificates', // you must set a valid URL here else you will get an error
theme: 'fa',
uploadExtraData: function() {
return {
_token: "{{ csrf_token() }}",
};
},
allowedFileExtensions: ['jpg', 'png', 'gif', 'pdf', 'jpeg'],
overwriteInitial: false,
maxFileSize: 500,
maxFilesNum: 10,
//allowedFileTypes: ['image', 'video', 'flash'],
slugCallback: function (filename) {
return filename.replace('(', '_').replace(']', '_');
}
});
</script>
1.Use code like this to store uploaded file and associate it with your Applications
if ($request->hasFile('breg_cert')) {
if ($request->file('breg_cert')->isValid()) {
$imgName = basename($request->breg_cert->store(public_path('breg_cert')));
$applications->breg_cert = $imgName;
}
}
https://laravel.com/docs/5.8/requests#storing-uploaded-files
To store an uploaded file, you will typically use one of your configured filesystems. The UploadedFile class has a store method which will move an uploaded file to one of your disks, which may be a location on your local filesystem or even a cloud storage location like Amazon S3.
The store method accepts the path where the file should be stored relative to the filesystem's configured root directory. This path should not contain a file name, since a unique ID will automatically be generated to serve as the file name.
To handle delete/replace create a corresponding controller method and POST route and then provide the route to deleteUrl option.
In the above method check the filename associated and unlink it. (actual code depends on what dd($request); output)
To show stored image as preview add option to $("#file-0a").fileinput({
initialPreview: [
"<img src='/images/path-to.jpg' class='file-preview-image'>",
],
I'm trying build an Asp.net web api for posting files. I found the following example in
https://code.msdn.microsoft.com/AngularJS-with-Web-API-22f62a6e
The Web API method is:
[RoutePrefix("api/photo")]
public class PhotoController : ApiController
{
private IPhotoManager photoManager;
public PhotoController()
: this(new LocalPhotoManager(HttpRuntime.AppDomainAppPath + #"\Album"))
{
}
public PhotoController(IPhotoManager photoManager)
{
this.photoManager = photoManager;
}
// GET: api/Photo
public async Task<IHttpActionResult> Get()
{
var results = await photoManager.Get();
return Ok(new { photos = results });
}
// POST: api/Photo
public async Task<IHttpActionResult> Post()
{
// Check if the request contains multipart/form-data.
if(!Request.Content.IsMimeMultipartContent("form-data"))
{
return BadRequest("Unsupported media type");
}
try
{
var photos = await photoManager.Add(Request);
return Ok(new { Message = "Photos uploaded ok", Photos = photos });
}
catch (Exception ex)
{
return BadRequest(ex.GetBaseException().Message);
}
}
And the file uploader html code: (I added a text input <input type="text" id="test" value="testit" /> for test.
<form name="newPhotosForm" role="form" enctype="multipart/form-data" ng-disabled="appStatus.busy || photoManagerStatus.uploading">
<div class="form-group" ng-hide="hasFiles">
<label for="newPhotos">select and upload new photos</label>
<input type="file" id="newPhotos" class="uploadFile" accept="image/*" eg-files="photos" has-files="hasFiles" multiple>
<input type="text" id="test" value="testit" /> <!--- Added a text input for test -->
</div>
<div class="form-group" ng-show="hasFiles && !photoManagerStatus.uploading">
<ul class="list-inline">
<li><strong>files:</strong></li>
<li ng-repeat="photo in photos"> {{photo.name}}</li>
</ul>
<input class="btn btn-primary" type="button" eg-upload="upload(photos)" value="upload">
<input class="btn btn-warning" type="reset" value="cancel" />
</div>
<div class="form-group" ng-show="photoManagerStatus.uploading">
<p class="help-block">uploading</p>
</div>
</form>
The JS upload function:
function upload(photos)
{
service.status.uploading = true;
appInfo.setInfo({ busy: true, message: "uploading photos" });
var formData = new FormData();
angular.forEach(photos, function (photo) {
formData.append(photo.name, photo);
});
return photoManagerClient.save(formData)
.$promise
.then(function (result) {
if (result && result.photos) {
result.photos.forEach(function (photo) {
if (!photoExists(photo.name)) {
service.photos.push(photo);
}
});
}
appInfo.setInfo({message: "photos uploaded successfully"});
return result.$promise;
},
function (result) {
appInfo.setInfo({message: "something went wrong: " + result.data.message});
return $q.reject(result);
})
['finally'](
function () {
appInfo.setInfo({ busy: false });
service.status.uploading = false;
});
}
However, it seems the value of the added input test cannot be passed to the Web API code?
You need to add custom DTO/POCO class, set the values and then pass it as parameter to your post method. Since file is not a simple type default MediaTypeFormatter of webAPI won't work so you need to build your custom MediaTypeFormatter.
Sample POCO class
Public Class Attachment
{
public string Input {get;set;}
public byte[] Content{get;set;}
}
Custom Media formatter as below
public class CustomFormatter : MediaTypeFormatter
{
/// <summary>
///
/// </summary>
public CustomFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("multipart/form-data"));
}
public override bool CanReadType(Type type)
{
return type == typeof(Attachment);
}
public override bool CanWriteType(Type type)
{
return false;
}
public async override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
{
var provider = await content.ReadAsMultipartAsync();
var modelContent = provider.Contents
.FirstOrDefault(c => c.Headers.ContentType.MediaType == "application/json");
var attachment = await modelContent.ReadAsAsync<Attachment>();
var fileContents = provider.Contents
.Where(c => c.Headers.ContentType.MediaType == "image/jpeg").FirstOrDefault(); // or whatever is the type of file to upload
attachment.Content = await fileContents.ReadAsByteArrayAsync();
return attachment;
}
}
Register the custom media formatter:
private void ConfigureWebApi(HttpConfiguration config)
{
//other code here
config.Formatters.Add(new CustomFormatter());
}
Pass the POCO to your Web-API Controller
public async Task<IHttpActionResult> Post(Attachment attachment)
{
I haven't tested this in Visual Studio, but this is the approach you need to follow
More information here:
http://www.asp.net/web-api/overview/formats-and-model-binding/media-formatters
And a sample here
http://blog.marcinbudny.com/2014/02/sending-binary-data-along-with-rest-api.html#.V5MDDzV7qYg
I'm trying to upload multiple files to server.
The file is being stored in a variable.
When I click upload the client is sending that variable empty.
Here is my html
<div class = "control-group form-group col-md-12"
ng-class = "{'has-error':newAsset.OSGImages.$invalid && newAsset.OSGImages.$dirty}" ng-if = "showUploadFile(4)">
<label>OSG Images (max 3 MB)</label>
<input type="file" multiple ngf-select="" ng-model="newAssetForm.OSGImages" name = "OSGImages" ngf-max-size="3 MB">
<p ng-repeat="image in newAssetForm.OSGImages">
{{image.name}}
</p>
<span class = "help-block has-error" ng-if="newAsset.OSGImages.$dirty">
</span>
</div>
Here is my js code:
enter code var fileReader = new FileReader();
fileReader.readAsArrayBuffer($scope.newAssetForm.OSGImages[0]);
fileReader.onload = function(e) {
console.log(e);
Upload.upload({
url: '/api/uploadAsset',
headers: {
'Content-Type': 'multipart/form-data'
},
data: {
'projectId': $scope.projectId,
'loadValueType' : $scope.newAssetForm.loadValueType,
'outputVideoLink': $scope.newAssetForm.outputVideoLink,
'isActive': $scope.newAssetForm.isActive,
'PImageSet': PImageSet,
inputImageUrl: $scope.newAssetForm.inputImageUrl,
markerPattFile: $scope.newAssetForm.markerPattFile,
cinema: $scope.newAssetForm.cinema,
objFile: $scope.newAssetForm.objFile,
mtlFile: $scope.newAssetForm.mtlFile,
PImage: $scope.newAssetForm.PImage,
osgFile: $scope.newAssetForm.OSGFile,
osgImage: e.target.result,
},
})
.then(function onSuccess(result){
$scope.$emit('create_asset', result.data);
$modalInstance.close();
})
I tried uploading with postman and the server is getting the files.
Also, the console logs print the files correctly.
Why the client is sending empty variable?
I am using Symfony2.8 With aviaryeditor Image Editor. The Scene is that I have from with one file upload field. I wanted to allow user to upload images and do some editing with images (cropping, resizing, effects) then upload it to the server. And on the backend i get the file. Do some checks and validation and upload it on my local file system of s3.
What i have done so far is, I allow user to upload the image from the user and dislay the uploaded image in the form. On image click the editors pops up and after editing the gives the new url (s3 url of avairy api).
$builder
->add('media', 'file', array(
'data_class' => null,
'label' => ucfirst('Choose Domicile File'),
'attr' => array('class' => 'form-control')
)
)
<div class = "form-group col-xs-5">
<label class="control-label">{{ form_label(domicileForm.media) }}</label>
<div class="text-center">
{{form_widget (domicileForm.media, {'attr': {'class': 'form-control'}})}}
</div>
<img id="blah" src="#" alt="your image"
class="img-responsive img-thunmbail"
onclick="return launchEditor(this.id, this.src);" />
</div>
and with js
<script>
$(document).ready(function() {
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#blah').attr('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
}
$("#pncmisdashboard_bundle_dimicile_type_media").change(function(){
readURL(this);
});
});
</script>
<script type="text/javascript" src="http://feather.aviary.com/js/feather.js"></script>
<!-- Instantiate Feather -->
<script type='text/javascript'>
var featherEditor = new Aviary.Feather({
apiKey: '43232',
apiVersion: 3,
theme: 'light', // Check out our new 'light' and 'dark' themes!
tools:'crop,resize,color,sharpness,text',
appendTo: '',
onSave: function(imageID, newURL) {
var img = document.getElementById(imageID);
$(imageID).attr('src', newURL);
// //copy the url to the hidden form field
// $('#pncmisdashboard_bundle_dimicile_type_media').val(newURL);
$('#pncmisdashboard_bundle_dimicile_type_media').attr('value', newURL);
img.src = newURL;
alert(imageID);
alert(newURL);
alert(imageID);
},
onError: function(errorObj) {
alert(errorObj.message);
}
});
function launchEditor(id, src) {
featherEditor.launch({
image: id,
url: src
});
return false;
}
</script>
and after the api successfully return the url of new image, I am setting this url to media (file type) field. But it's not happening. it saves the orignal image that was first upload not the new one.