具有相同名称的多个文件未在环回中上传
Multiple file with same name is not uploading in loopback
我正在使用 REST API url Loopback3 上传文件。提交表单后,将插入值并保存文件。现在,如果我上传的文件与已经退出的文件相同,则该文件不会 stored.How 重命名文件,后跟一些随机数并保存。
HTML
<form id="myForm" novalidate class="formval" >
<div class="form-row">
<div class="form-group col-md-6">
<input type="text" class="form-control" id="firstname" name="firstname" placeholder="First Name" required>
</div>
<div class="form-group col-md-6">
<input type="text" class="form-control" id="lastname" name="lastname" placeholder="Last Name" required>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-12">
<textarea class="form-control" id="message" name="message" placeholder="Message"></textarea>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-8">
<input type="file" id="resume" class="form-control" name="resume" accept=".doc,.docx,.pdf" required />
</div>
</div>
<input type="submit" class="btn btn-primary mt-10" id="item-submit" value="submit">
</form>
脚本:
var $firstname, $lastname, $message, $resume, $inserted_date, ins_date;
var apiUrl = 'http://localhost:3000/api/';
$(document).ready(function() {
var random = Math.random( );
$('#myForm').on('submit', handleForm);
ins_date=new Date($.now()).toLocaleString();
$firstname = $('#firstname');
$lastname = $('#lastname');
$message = $('#message');
$resume = $('#resume');
$inserted_date=ins_date;
});
function handleForm(e) {
e.preventDefault();
var career = {
firstname:$firstname.val(),
lastname:$lastname.val(),
message:$message.val(),
inserted_date:ins_date
}
console.log(career);
$.post(apiUrl + 'careers', career).then(function(res) {
career = res;
var promises = [];
if($resume.val() != '') {
console.log('i need to process the resume upload');
promises.push(sendFile($resume.get(0).files[0], apiUrl + 'attachments/resume/upload'));
}
Promise.all(promises).then(function(results) {
console.log('back from all promises', results);
if(promises.length >= 1) {
results.forEach(function(resultOb) {
if(resultOb.result.files && resultOb.result.files.file[0].container) {
career[resultOb.result.files.file[0].container] = resultOb.result.files.file[0].name;
}
});
console.dir(career);
var id = career.id;
delete career.id;
$.post(apiUrl + 'careers/'+id+'/replace', career).then(function() {
});
} else {
}
});
});
}
function sendFile(file, url) {
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
var fd = new FormData();
xhr.open("POST", url, true);
xhr.onreadystatechange = function() {
if(xhr.readyState == 4 && xhr.status == 200) {
resolve(JSON.parse(xhr.responseText));
}
};
fd.append('file', file);
xhr.send(fd);
$(".alert-success").removeClass("d-none");
$(".alert-success").fadeTo(2000, 500).slideUp(500, function(){
$(".alert-success").slideUp(500);
});
$('#myForm')[0].reset();
});
}
尝试根据它们的创建顺序以不同的方式命名它们。
我已阅读您的请求,了解到您正在尝试使用环回上传文件。即使使用环回上传也能正常工作,但您的要求是上传同名文件吗?
如果是,您将使用版本控制存储文件,方法是在末尾行“_v1”中添加一些关键文本,您可以在其中检查新上传时的增量值。或者,一个简单的方法是您可以连接 Unix 格式的时间戳,这将是一系列数字并且每秒都是唯一的。所以你可以把这个名字存到DB里供你参考。
例如:
var filename = filename +'_'+ new Date().getTime();
您需要为每个上传的文件添加唯一的文件名。最简单(可能不是最好)的方法是添加当前时间戳。
将文件附加到 FormData 对象的语法是:formData.append(name, value);
或 formData.append(name, value, filename);
。如果您使用第一个版本并跳过 filename
参数,它默认为 file
的 name
属性。 MDN
在您的情况下,您不需要默认文件名,您需要为其添加时间戳。
您可以使用 Date.now()
或 new Date().getTime()
获取当前时间戳。在这种情况下最好使用 Date.now()
,因为它比 new Date().getTime()
.
快两倍多(而且输入更少)
因此您现在可以像这样生成一个唯一的文件名:
`${Date.now()}_${file.name}`
我们把时间放在第一位,因为 file.name
包含文件扩展名,而您需要它。
这将生成类似这样的东西 '1553690001341_whatever.jpg'
但是,如果将文件名放在前面,您将得到 'whatever.jpg_1553690001341'
,因此该文件将不会以文件扩展名保存在服务器上,如果有人从服务器下载它,他们将不知道如何打开它。
我们还使用反引号在字符串中使用变量,这只会让事情变得更容易一些。如果你不使用反引号,你可以像这样使用 +
得到相同的结果:
Date.now() + '_' + file.name
现在您需要做的就是在将文件附加到 FormData 时也添加文件名。所以写
fd.append('file', file, `${Date.now()}_${file.name}`);
而不是
fd.append('file', file);
PS: 像这样的事情应该由后端处理 API
您似乎在使用 loopback-component-storage。
我建议在创建数据源时简单地使用 nameConflict
属性,如下例所示 - 因为看起来您已经检索到已上传的文件名:
在你的 Loopback 的 server/server.js
var ds = loopback.createDataSource({
connector: require('loopback-component-storage'),
provider: 'filesystem',
root: path.join(__dirname, 'attachments'),
nameConflict: 'makeUnique' // simply add this line!
});
var container = ds.createModel('attachments');
Loopback 可以在保存时自行重命名文件:
https://loopback.io/doc/en/lb3/Storage-component.html#renaming-files
我正在使用 REST API url Loopback3 上传文件。提交表单后,将插入值并保存文件。现在,如果我上传的文件与已经退出的文件相同,则该文件不会 stored.How 重命名文件,后跟一些随机数并保存。
HTML
<form id="myForm" novalidate class="formval" >
<div class="form-row">
<div class="form-group col-md-6">
<input type="text" class="form-control" id="firstname" name="firstname" placeholder="First Name" required>
</div>
<div class="form-group col-md-6">
<input type="text" class="form-control" id="lastname" name="lastname" placeholder="Last Name" required>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-12">
<textarea class="form-control" id="message" name="message" placeholder="Message"></textarea>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-8">
<input type="file" id="resume" class="form-control" name="resume" accept=".doc,.docx,.pdf" required />
</div>
</div>
<input type="submit" class="btn btn-primary mt-10" id="item-submit" value="submit">
</form>
脚本:
var $firstname, $lastname, $message, $resume, $inserted_date, ins_date;
var apiUrl = 'http://localhost:3000/api/';
$(document).ready(function() {
var random = Math.random( );
$('#myForm').on('submit', handleForm);
ins_date=new Date($.now()).toLocaleString();
$firstname = $('#firstname');
$lastname = $('#lastname');
$message = $('#message');
$resume = $('#resume');
$inserted_date=ins_date;
});
function handleForm(e) {
e.preventDefault();
var career = {
firstname:$firstname.val(),
lastname:$lastname.val(),
message:$message.val(),
inserted_date:ins_date
}
console.log(career);
$.post(apiUrl + 'careers', career).then(function(res) {
career = res;
var promises = [];
if($resume.val() != '') {
console.log('i need to process the resume upload');
promises.push(sendFile($resume.get(0).files[0], apiUrl + 'attachments/resume/upload'));
}
Promise.all(promises).then(function(results) {
console.log('back from all promises', results);
if(promises.length >= 1) {
results.forEach(function(resultOb) {
if(resultOb.result.files && resultOb.result.files.file[0].container) {
career[resultOb.result.files.file[0].container] = resultOb.result.files.file[0].name;
}
});
console.dir(career);
var id = career.id;
delete career.id;
$.post(apiUrl + 'careers/'+id+'/replace', career).then(function() {
});
} else {
}
});
});
}
function sendFile(file, url) {
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
var fd = new FormData();
xhr.open("POST", url, true);
xhr.onreadystatechange = function() {
if(xhr.readyState == 4 && xhr.status == 200) {
resolve(JSON.parse(xhr.responseText));
}
};
fd.append('file', file);
xhr.send(fd);
$(".alert-success").removeClass("d-none");
$(".alert-success").fadeTo(2000, 500).slideUp(500, function(){
$(".alert-success").slideUp(500);
});
$('#myForm')[0].reset();
});
}
尝试根据它们的创建顺序以不同的方式命名它们。
我已阅读您的请求,了解到您正在尝试使用环回上传文件。即使使用环回上传也能正常工作,但您的要求是上传同名文件吗?
如果是,您将使用版本控制存储文件,方法是在末尾行“_v1”中添加一些关键文本,您可以在其中检查新上传时的增量值。或者,一个简单的方法是您可以连接 Unix 格式的时间戳,这将是一系列数字并且每秒都是唯一的。所以你可以把这个名字存到DB里供你参考。
例如:
var filename = filename +'_'+ new Date().getTime();
您需要为每个上传的文件添加唯一的文件名。最简单(可能不是最好)的方法是添加当前时间戳。
将文件附加到 FormData 对象的语法是:formData.append(name, value);
或 formData.append(name, value, filename);
。如果您使用第一个版本并跳过 filename
参数,它默认为 file
的 name
属性。 MDN
在您的情况下,您不需要默认文件名,您需要为其添加时间戳。
您可以使用 Date.now()
或 new Date().getTime()
获取当前时间戳。在这种情况下最好使用 Date.now()
,因为它比 new Date().getTime()
.
因此您现在可以像这样生成一个唯一的文件名:
`${Date.now()}_${file.name}`
我们把时间放在第一位,因为 file.name
包含文件扩展名,而您需要它。
这将生成类似这样的东西 '1553690001341_whatever.jpg'
但是,如果将文件名放在前面,您将得到 'whatever.jpg_1553690001341'
,因此该文件将不会以文件扩展名保存在服务器上,如果有人从服务器下载它,他们将不知道如何打开它。
我们还使用反引号在字符串中使用变量,这只会让事情变得更容易一些。如果你不使用反引号,你可以像这样使用 +
得到相同的结果:
Date.now() + '_' + file.name
现在您需要做的就是在将文件附加到 FormData 时也添加文件名。所以写
fd.append('file', file, `${Date.now()}_${file.name}`);
而不是
fd.append('file', file);
PS: 像这样的事情应该由后端处理 API
您似乎在使用 loopback-component-storage。
我建议在创建数据源时简单地使用 nameConflict
属性,如下例所示 - 因为看起来您已经检索到已上传的文件名:
在你的 Loopback 的 server/server.js
var ds = loopback.createDataSource({
connector: require('loopback-component-storage'),
provider: 'filesystem',
root: path.join(__dirname, 'attachments'),
nameConflict: 'makeUnique' // simply add this line!
});
var container = ds.createModel('attachments');
Loopback 可以在保存时自行重命名文件: https://loopback.io/doc/en/lb3/Storage-component.html#renaming-files